package pl.umk.mat.fred.unicore.urc.storagemanagement.views;

import java.util.List;
import java.util.Map;

import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableCursor;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import pl.umk.mat.fred.unicore.urc.storagemanagement.StorageManagementActivator;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.RunTimeMeterThreadAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.actions.StopTimeMeterThreadAction;
import pl.umk.mat.fred.unicore.urc.storagemanagement.preferences.PreferenceConstants;
import pl.umk.mat.fred.unicore.urc.storagemanagement.unicore.Storage;

public class TimeMeterView extends ViewPart {

	private TableViewer viewer;
	private TimeMeterModelProvider timeMeterModelProvider;
	private List<Storage> storages;
	private final int SELECTED_COLUMN_WIDTH = 130;
	private final int UNSELECTED_COLUMN_WIDTH = 65;
	private int columnCount = 0;
	
	public static final Color RED_COLOR = new Color(PlatformUI.getWorkbench().getDisplay(), 255, 101, 101);
	public static final Color YELLOW_COLOR = new Color(PlatformUI.getWorkbench().getDisplay(), 255, 245, 101);
	public static final Color GREEN_COLOR = new Color(PlatformUI.getWorkbench().getDisplay(),160, 255, 101);
	
	RunTimeMeterThreadAction runAction = null;
	StopTimeMeterThreadAction stopAction = null;
	
	public TimeMeterView() {
		super();
		storages = StorageManagementActivator.getDefault().getStorageList();
		StorageManagementActivator.getDefault().setTimeMeterView(this);
		timeMeterModelProvider = new TimeMeterModelProvider();
	}

	public void createPartControl(Composite parent) {
		createViewer(parent);
	}
	
	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL | SWT.BORDER);
		createColumns(parent, viewer);
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		final TableCursor cursor = new TableCursor(table, SWT.NONE);
		cursor.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				if (cursor.getColumn() != 0) {
					int pos = 0;
					for (TableColumn col : table.getColumns()) {
						if (pos != 0) {
							col.setWidth(UNSELECTED_COLUMN_WIDTH);
						}
						pos++;
					}
					table.getColumn(cursor.getColumn()).setWidth(SELECTED_COLUMN_WIDTH);
				}
			}
		});
		viewer.setContentProvider(new ArrayContentProvider());
		viewer.setInput(timeMeterModelProvider.getInput());
		
		fillLocalToolBar(getViewSite().getActionBars().getToolBarManager());
	}

	public TableViewer getViewer() {
		return viewer;
	}

	private void createColumns(final Composite parent, final TableViewer viewer) {
		String[] titles = { "from \\ to", "localhost" };

		TableViewerColumn col = createTableViewerColumn(titles[0], 110);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Map<String, Object> map = (Map<String, Object>) element;
				Object obj = map.get("name");
				if (obj == null) {
					return null;
				}
				return obj.toString();
			}
			
			@Override
			public Color getBackground(Object element) {
				return null;
			}
		});
		columnCount++;

		col = createTableViewerColumn(titles[1], UNSELECTED_COLUMN_WIDTH);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Map<String, Object> map = (Map<String, Object>) element;
				Object obj = map.get("localhost");
				if (obj == null) {
					return null;
				}
				String unit = timeMeterModelProvider.getTransferUnit();
				return convertSpeedByUnit((Integer) obj, unit);
			}

			@Override
			public Color getBackground(Object element) {
				Map<String, Object> map = (Map<String, Object>) element;
				Object obj = map.get("localhost");
				if (obj == null) {
					return null;
				}
				return getColorForSpeed((Integer) obj);
			}
		});
		columnCount++;
		
		for (final Storage s : storages) {
			addColumn(s, columnCount++);
		}
	}
	
	private void addColumn(final Storage s, int currentCol) {
		TableViewerColumn col = createTableViewerColumn(s.getName(), UNSELECTED_COLUMN_WIDTH);
		final int j = currentCol++;
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Map<String, Object> map = (Map<String, Object>) element;
				Object obj = map.get(s.getUrl());
				if (obj == null) {
					return null;
				}
				String unit = timeMeterModelProvider.getTransferUnit();
				return convertSpeedByUnit((Integer) obj, unit);
			}
			
			@Override
			public Color getBackground(Object element) {
				Map<String, Object> map = (Map<String, Object>) element;
				Object obj = map.get(s.getUrl());
				if (obj == null) {
					return null;
				}
				return getColorForSpeed((Integer) obj);
			}
		});
	}
	
	
	private TableViewerColumn createTableViewerColumn(String title, int bound) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
				SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}

	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
	public TableViewer getTableViewer() {
		return viewer;
	}
	
	public int getColumnSize() {
		if (viewer.getTable() != null) {
			return viewer.getTable().getColumns().length;
		}
		return 0;
	}
	
	private Color getColorForSpeed(int speed) {
		Color color = RED_COLOR;
		if (speed > StorageManagementActivator.getDefault().getPreferenceStore().getInt(PreferenceConstants.P_RED_YELLOW_COLOR) * 1024) {
			color = YELLOW_COLOR;
			if (speed > StorageManagementActivator.getDefault().getPreferenceStore().getInt(PreferenceConstants.P_YELLOW_GREEN_COLOR) * 1024) {
				color = GREEN_COLOR;
			}
		}
		return color;
	}

	public void refreshInput() {
		getTableViewer().setInput(timeMeterModelProvider.getInput());
	}
	
	private String convertSpeedByUnit(Integer val, String unit) {
		if (timeMeterModelProvider.MEGABYTES_PER_SECOND.equals(unit)) {
			return getSpeedWithAdequatePrecision(val / 1048576.0) + " " + unit; // 1048576 = 1024*1024
		}
		if (timeMeterModelProvider.KILOBYTES_PER_SECOND.equals(unit)) {
			return getSpeedWithAdequatePrecision(val / 1024) + " " + unit;
		}
		return getSpeedWithAdequatePrecision(val) + " " + unit;
	}
	
	private String getSpeedWithAdequatePrecision(double speed) {
		String result;
		if (speed < 10) {
			if (speed < 1) {
				int num = 0;
				double speedTmp = speed;
				while (speedTmp < 1) {
					num++;
					speedTmp *= 10;
				}
				result = String.format("%." + num + "f", speed);
			} else {
				result = String.format("%.2f", speed);
			}
		} else {
			result = String.format("%.0f", speed);
		}
		return result;
	}
	
	private void fillLocalToolBar(IToolBarManager manager) {
		runAction = new RunTimeMeterThreadAction(this);
		manager.add(runAction);
		
		stopAction = new StopTimeMeterThreadAction(this);
		manager.add(stopAction);
	}
	
	public RunTimeMeterThreadAction getRunTimeMeterThreadAction() {
		return runAction;
	}
	
	public StopTimeMeterThreadAction getStopTimeMeterThreadAction() {
		return stopAction;
	}

	public void addStorage(final Storage storage) {
		PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
			@Override
			public void run() {
				addColumn(storage, columnCount++);
			}
		});		
	}
}
